package au.com.iglootech.silmbox_sm.dao;

import java.util.Collection;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.jdo.PersistenceManagerFactory;
import javax.persistence.criteria.DomainObject;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.ObjectRetrievalFailureException;
import org.springframework.orm.jdo.JdoTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.google.appengine.api.datastore.Key;

@Repository
@Transactional(readOnly = false)
public class GenericDao {

    @Autowired
    private PersistenceManagerFactory pmf;

    private JdoTemplate jdoTemplate;

    @PostConstruct
    void createJdoTemplate() {
        jdoTemplate = new JdoTemplate(pmf);
    }

    @Transactional(readOnly = true)
    public <T extends DomainObject> T findByKey(Class<T> clazz, Key id) {
        @SuppressWarnings("unchecked")
        T entity = (T) jdoTemplate.getObjectById(clazz, id);

        if (entity == null) {
            throw new ObjectRetrievalFailureException(clazz, id);
        }
        return entity;
    }

    @Transactional(readOnly = true)
    @SuppressWarnings("unchecked")
    public <T extends DomainObject> Collection<T> findAll(Class<T> clazz) {
        return jdoTemplate.detachCopyAll(jdoTemplate.find(clazz));
    }

    @Transactional
    @SuppressWarnings("unchecked")
    public <T extends DomainObject> void remove(T domainObj) {
        T domainObject = (T) jdoTemplate.getObjectById(domainObj.getClass(),
                domainObj.key());
        jdoTemplate.deletePersistent(domainObject);
    }

    @Transactional(readOnly = true)
    @SuppressWarnings("unchecked")
    public <T extends DomainObject> Collection<T> findByNamedQuery(Class<T> clazz, String namedQuery, Map<String, Object> values) {
        return jdoTemplate.findByNamedQuery(clazz, namedQuery, values);
    }


    @Transactional
    @SuppressWarnings("unchecked")
    public <T extends Object> T save(T domainObj) {
        return (T) jdoTemplate.makePersistent(domainObj);
    }

    @Transactional
    public void flush() {
        jdoTemplate.flush();
    }

}
